package top.zywork.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import top.zywork.constant.CommonConstant;
import top.zywork.dos.*;
import top.zywork.dto.UserUserSocialDTO;
import top.zywork.dto.UserWalletDTO;
import top.zywork.enums.*;
import top.zywork.exception.GlobalException;
import top.zywork.ext.dos.CourierExtractingExtDO;
import top.zywork.ext.service.CourierExtractingExtService;
import top.zywork.mapper.SchoolOrderAddressMapper;
import top.zywork.mapper.SchoolOrderMapper;
import top.zywork.query.wx.SchoolOrderWxQuery;
import top.zywork.security.JwtUtils;
import top.zywork.security.SecurityUtils;
import top.zywork.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import top.zywork.strategy.order.BaseOrder;
import top.zywork.utils.ODDGenerator;
import top.zywork.vo.ResponseStatusVO;
import top.zywork.vo.wx.*;
import top.zywork.weixin.WeixinMsgUtils;
import top.zywork.weixin.WeixinUtils;
import top.zywork.weixin.XcxTemplateMsg;
import top.zywork.wx.query.CourierHallQuery;
import top.zywork.wx.response.CourierHallResponse;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author
 * @since 2020-10-13
 */
@Service
@Slf4j
public class SchoolOrderServiceImpl extends ServiceImpl<SchoolOrderMapper, SchoolOrderDO> implements SchoolOrderService {




    /**
     * 地址
     */
    @Autowired
    private ShippingAddressExServiceImpl shippingAddressExService;

    /**
     * 学校
     */
    @Autowired
    private SchoolService schoolService;

    /**
     * 取件点
     */
    @Autowired
    private SchoolPlaceService schoolPlaceService;

    /**
     * 包裹大小
     */
    @Autowired
    private SchoolParcelService schoolParcelService;

    @Autowired
    private UserCertificationService userCertificationService;


    @Resource
    private SchoolOrderAddressMapper schoolOrderAddressMapper;

    @Autowired
    private CourierExtractingExtService courierExtractingExtService;

    /**
     * 用户资金表
     */
    @Autowired
    private UserWalletService userWalletService;

    @Autowired
    private BaseOrder baseOrder;

    @Autowired
    private UserUserSocialService userUserSocialService;


    /**
     * @param schoolOrderPlaceVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResponseStatusVO placeOrder(SchoolOrderPlaceVo schoolOrderPlaceVo) {

        // 生成订单号
        String orderId = ODDGenerator.getC();

        long userId = SecurityUtils.getJwtUser().getUserId();
        // 检查学校是否存在
        SchoolDO schoolDO = schoolService.checkSchool(schoolOrderPlaceVo.getSchoolId());
        if(schoolDO == null){
            return ResponseStatusVO.error("学校不存在",null);
        }

        // 判断地址是否是当前登录用户
        ShippingAddressDO shippingAddressDO = shippingAddressExService.getOne(new QueryWrapper<ShippingAddressDO>()
                .eq("is_active", CommonConstant.IS_ACTIVE_TRUE)
                .eq("user_id", userId)
                .eq("id", schoolOrderPlaceVo.getAddressId()));
        if(shippingAddressDO == null){
            return ResponseStatusVO.error("地址不存在",null);
        }

        // 取件点
        SchoolPlaceDO schoolPlaceDO = schoolPlaceService.checkPlace(schoolOrderPlaceVo.getSchoolId(), schoolOrderPlaceVo.getPlaceId());
        if(schoolPlaceDO == null){
            return ResponseStatusVO.error("取件点不存在",null);
        }

        // 包裹大小
        SchoolParcelDO schoolParcelDO = schoolParcelService.checkParcel(schoolOrderPlaceVo.getSchoolId(), schoolOrderPlaceVo.getParcelId());
        if(schoolParcelDO == null){
            return ResponseStatusVO.error("包裹大小不存在",null);
        }

        /**
         * 保存订单信息
         */
        SchoolOrderDO schoolOrderDO = new SchoolOrderDO();
        // 订单ID
        schoolOrderDO.setId(orderId);
        // 下单用户ID
        schoolOrderDO.setUserId(userId);
        // 学校ID
        schoolOrderDO.setSchoolId(schoolDO.getId());
        // 备注、取件码、短信
        schoolOrderDO.setNotes(schoolOrderPlaceVo.getNotes());
        // 包裹大小
        StringBuilder parcel = new StringBuilder(schoolParcelDO.getParcel()).append("（").append(schoolParcelDO.getNotes()).append("）");
        schoolOrderDO.setParcel(parcel.toString());
        // 取件点
        StringBuilder place = new StringBuilder(schoolPlaceDO.getPlace()).append("（").append(schoolPlaceDO.getNotes()).append("）");
        schoolOrderDO.setPlace(place.toString());
        // 包裹对应的金额
        schoolOrderDO.setTotalAmount(schoolParcelDO.getAmount());
        // 实付金额
        schoolOrderDO.setPayAmount(schoolParcelDO.getAmount());
        // 优惠金额
        schoolOrderDO.setDiscountAmount(new BigDecimal("0"));

        // 查询对应抽成表
        CourierExtractingExtDO one = courierExtractingExtService.getOne(new QueryWrapper<CourierExtractingExtDO>()
                .eq("school_id", schoolOrderPlaceVo.getSchoolId())
                .eq("type", "KDDN"));
        if(one == null){
            // 如果未设置抽成表则按订单实际总金额给予
            schoolOrderDO.setCommission(schoolParcelDO.getAmount());
        }else{
            BigDecimal extracting = schoolParcelDO.getAmount().multiply(BigDecimal.valueOf(one.getExtracting())).divide(BigDecimal.valueOf(100));
            schoolOrderDO.setCommission(schoolParcelDO.getAmount().subtract(extracting));
        }

        // 派送时间
        schoolOrderDO.setDelivery(schoolOrderPlaceVo.getDelivery());
        // 是否激活状态
        schoolOrderDO.setIsActive(CommonConstant.IS_ACTIVE_FALSE);
        // 支付状态默认为待支付
        schoolOrderDO.setPayStatus(PayStatusEnum.TO_BE_PAID.getCode());
        // 订单创建时间
        schoolOrderDO.setCreateTime(new Date());
        // 订单更新时间
        schoolOrderDO.setUpdateTime(new Date());

        // 30分钟超时时间 当前时间+30分钟
        schoolOrderDO.setTimeouts(expTime(30*60*1000));

        // 保存订单
        baseMapper.insert(schoolOrderDO);

        // 保存订单对应的配送地址
        SchoolOrderAddressDO schoolOrderAddressDO = new SchoolOrderAddressDO();
        BeanUtils.copyProperties(shippingAddressDO,schoolOrderAddressDO);
        schoolOrderAddressDO.setId(orderId);
        schoolOrderAddressDO.setCreateTime(new Date());
        schoolOrderAddressMapper.insert(schoolOrderAddressDO);

        return ResponseStatusVO.ok("订单保存成功",orderId);
    }

    @Override
    public IPage<SchoolUserOrderWxVO> order(SchoolOrderWxQuery schoolOrderWxQuery) {
        long userId = SecurityUtils.getJwtUser().getUserId();
        Page page = new Page(schoolOrderWxQuery.getLimit(),schoolOrderWxQuery.getSize());
        QueryWrapper<SchoolOrderDO> queryWrapper = new QueryWrapper<>();
        // 未支付的订单激活条件为FALSE
        queryWrapper.eq("is_active",CommonConstant.IS_ACTIVE_TRUE);
        queryWrapper.eq("pay_status",PayStatusEnum.HAVE_TO_PAY.getCode());
        queryWrapper.eq("user_id",userId);
        // 订单条件 订单状态
        queryWrapper.eq(schoolOrderWxQuery.getOrderStatus()!=null,"status",schoolOrderWxQuery.getOrderStatus());
        IPage<SchoolOrderDO> iPage = baseMapper.selectPage(page, queryWrapper);

        IPage<SchoolUserOrderWxVO> userOrderWxVOIPage = new Page<>();
        BeanUtils.copyProperties(iPage,userOrderWxVOIPage);

        List<SchoolUserOrderWxVO> collect = iPage.getRecords().stream().map(e -> {
            SchoolUserOrderWxVO schoolUserOrderWxVO = new SchoolUserOrderWxVO();
            BeanUtils.copyProperties(e, schoolUserOrderWxVO);

            // 格式化的订单状态
            schoolUserOrderWxVO.setOrderStatus(SchoolOrderStatusEnum.getEnum(e.getStatus()).getValue());
            return schoolUserOrderWxVO;
        }).collect(Collectors.toList());

        userOrderWxVOIPage.setRecords(collect);
        return userOrderWxVOIPage;
    }

    @Override
    public ResponseStatusVO orderDetails(String orderId) {
        long userId = SecurityUtils.getJwtUser().getUserId();
        // 查询订单信息
        QueryWrapper<SchoolOrderDO> queryWrapper = new QueryWrapper<>();
        // 未支付的订单激活条件为FALSE
        queryWrapper.eq("is_active",CommonConstant.IS_ACTIVE_TRUE);
        queryWrapper.eq("user_id",userId);
        queryWrapper.eq("id",orderId);
        SchoolOrderDO schoolOrderDO = baseMapper.selectOne(queryWrapper);
        if(schoolOrderDO == null){
            return ResponseStatusVO.error("订单不存在",null);
        }
        // 查询地址信息
        SchoolOrderAddressDO schoolOrderAddressDO = schoolOrderAddressMapper.selectById(orderId);
        if(schoolOrderAddressDO == null){
            return ResponseStatusVO.error("订单地址异常",null);
        }
        // 数据格式化开始
        SchoolOrderDetailsWxVO wxVO = new SchoolOrderDetailsWxVO();
        // 订单数据格式化
        OrderDetails orderDetails = new OrderDetails();
        BeanUtils.copyProperties(schoolOrderDO,orderDetails);
        orderDetails.setOrderStatus(SchoolOrderStatusEnum.getEnum(schoolOrderDO.getStatus()).getValue());
        // 地址组装格式化
        AddressDetails addressDetails = new AddressDetails();
        addressDetails.setRealName(schoolOrderAddressDO.getRealName());
        addressDetails.setPhone(schoolOrderAddressDO.getPhone());
        addressDetails.setCombination(schoolOrderAddressDO.getSchool() + schoolOrderAddressDO.getStoriedBuilding() + schoolOrderAddressDO.getArea());

        // TODO 接单人用户信息查询  由于没有用户信息没扩展所以目前不查询

        wxVO.setOrderDetails(orderDetails);
        wxVO.setAddressDetails(addressDetails);
        return ResponseStatusVO.ok("查询成功",wxVO);
    }

    @Override
    public List<CourierHallResponse> courierHall(CourierHallQuery courierHallQuery) {
        List<CourierHallResponse> courierHallResponses = baseMapper.courierHall(courierHallQuery);
        return courierHallResponses;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResponseStatusVO courierOrder(String orderId) {
        long userId = SecurityUtils.getJwtUser().getUserId();
        // 判断当前用户是否已经认证为骑手
        UserCertificationDO one = userCertificationService.getOne(new QueryWrapper<UserCertificationDO>()
                .eq("user_id", userId)
                .eq("check_status", CertificationCheckStatusEnum.AUTHENTICATION_FAILED.getCode()));

        if(one == null){
            return ResponseStatusVO.error("请前往我的-申请骑手认证~",null);
        }

        // 通过订单id - 待接单状态 - 非当前用户id进行订单查询
        SchoolOrderDO result = baseMapper.selectOne(new QueryWrapper<SchoolOrderDO>()
                .eq("id", orderId)
                .eq("status", SchoolOrderStatusEnum.WAITING_LIST.getCode())
                .eq("is_active",CommonConstant.IS_ACTIVE_TRUE)
                // TODO 自己下单的不能自己接单 测试可以注释
                .ne("user_id", userId));
//        );
        if(result==null){
            return ResponseStatusVO.error("订单不存在",null);
        }

        // 修改代拿需求订单表
        result.setOrderUserId(userId);

        result.setStatus(SchoolOrderStatusEnum.HAVE_ORDER.getCode());

        baseMapper.updateById(result);

        // 骑手已经接单了就发送模板消息给下单人
        XcxTemplateMsg xcxTemplateMsg = new XcxTemplateMsg();
        xcxTemplateMsg.setTemplate_id("cqRw2ePGR1oDut_R9Up-zAfu63a6nWuW1s4GuXHEhKw");
        xcxTemplateMsg.setForm_id(orderId);
        // 查询用户第三方登录信息
        UserUserSocialDTO socialDO = (UserUserSocialDTO)userUserSocialService.getById(userId);
        log.info("接收模板消息用户的OPENID=>{}",socialDO.getUserSocialOpenid());
        xcxTemplateMsg.setTouser(socialDO.getUserSocialOpenid());
        Map<String, XcxTemplateMsg.MsgData> data  = new HashMap<>(16);
        data.put("character_string6.DATA", XcxTemplateMsg.MsgData.builder().value(orderId).build());
        data.put("date5.DATA", XcxTemplateMsg.MsgData.builder().value(result.getPlaceOrderTime().toString()).build());
//        data.put("date5.DATA", XcxTemplateMsg.MsgData.builder().value(result.getPlaceOrderTime().toString()).build());
        xcxTemplateMsg.setData(data);
        xcxTemplateMsg.setPage("http://www.baidu.com");
        baseOrder.sendTemplateMessage(xcxTemplateMsg);

        return ResponseStatusVO.ok("抢单成功",result.getId());
    }

    @Override
    public ResponseStatusVO orderUserDistribution(String orderId) {
        long userId = SecurityUtils.getJwtUser().getUserId();
        // 接单人id - 已接单状态 - 订单id
        SchoolOrderDO schoolOrderDO = baseMapper.selectOne(new QueryWrapper<SchoolOrderDO>()
                .eq("order_user_id", userId)
                .eq("status", SchoolOrderStatusEnum.HAVE_ORDER.getCode())
                .eq("is_active", CommonConstant.IS_ACTIVE_TRUE)
                .eq("id", orderId));
        if(schoolOrderDO == null){
            return ResponseStatusVO.error("订单不存在",null);
        }

        // 修改订单状态 为 配送中
        schoolOrderDO.setStatus(SchoolOrderStatusEnum.IN_THE_DISTRIBUTION.getCode());
        baseMapper.updateById(schoolOrderDO);

        // TODO 发送模板信息通知下单人 提示骑手已经接单



        return ResponseStatusVO.ok("",null);
    }

    /**
     * 这里考虑的是正常情况下需要骑手点击配送中才可以查询到订单信息然后下单人修改
     * @param orderId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResponseStatusVO userDistribution(String orderId) {
        long userId = SecurityUtils.getJwtUser().getUserId();
        // 下单人id - 配送中状态 - 订单id
        SchoolOrderDO schoolOrderDO = baseMapper.selectOne(new QueryWrapper<SchoolOrderDO>()
                .eq("user_id", userId)
                .eq("status", SchoolOrderStatusEnum.IN_THE_DISTRIBUTION.getCode())
                .eq("is_active", CommonConstant.IS_ACTIVE_TRUE)
                .eq("id", orderId));
        if(schoolOrderDO == null){
            return ResponseStatusVO.error("骑手可能没点击已取件哦~",null);
        }

        // 骑手佣金
        BigDecimal commission = schoolOrderDO.getCommission();

        // 修改订单为已完成
        schoolOrderDO.setStatus(SchoolOrderStatusEnum.HAS_BEEN_COMPLETED.getCode());
        baseMapper.updateById(schoolOrderDO);

        /**
         * 这边是下单人点击已完成操作的所以我们需要从订单中获取到接单人的用户id即可给接单人发送佣金
          */
        // 接单人id
        Long orderUserId = schoolOrderDO.getOrderUserId();
        UserWalletDTO userWalletDO = (UserWalletDTO)userWalletService.getById(orderUserId);
        if(userWalletDO==null){
            log.error("下单用户{}=>打入佣金至骑手{};订单号:{}",schoolOrderDO.getUserId(),schoolOrderDO.getOrderUserId(),schoolOrderDO.getId());
            throw new GlobalException("订单完结异常，请联系管理员。");
        }
        // 设置人民币余额也就是总金额
        userWalletDO.setRmbBalance(userWalletDO.getRmbBalance().add(commission));
        // 设置可用余额
        userWalletDO.setUsableRmbBalance(userWalletDO.getUsableRmbBalance().add(commission));

        // 保存骑手用户资金
        userWalletService.update(userWalletDO);

        // 保存骑手账目来源
        /**
         * transactionNo 这边的话可能是流水号可能是订单号，因为骑手佣金没有支付返回的那种字段。
         */
        baseOrder.saveAccountDetail(orderUserId,orderId, IncomeOutgoingTypeEnum.INCOME.getValue(),commission, AccountTypeEnum.DELIVERY_FOR.getValue(),null);

        return ResponseStatusVO.ok("确认成功",null);
    }

    /**
     * 增加的时间
     * @return
     */
    public Date expTime(int time){
        Date now = new Date();
        return new Date(now .getTime() + time);
    }

}
